/*
 * Copyright (c) 2009-2013 EvTech Project
 * All rights reserved.
 * 
 * This file is part of Game packet.
 *
 * Game packet is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Game packet is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Game packet.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package fi.honkalampisaatio.game.selection;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.EventObject;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.xml.bind.JAXBException;

import sun.awt.SunToolkit;

import fi.honkalampisaatio.game.game.GameEvent;
import fi.honkalampisaatio.game.game.GameEventListener;
import fi.honkalampisaatio.game.game.GamePanel;
import fi.honkalampisaatio.game.game.MediaResource;
import fi.honkalampisaatio.game.logging.GameLogger;
import fi.honkalampisaatio.game.xml.GameSettings;
import fi.honkalampisaatio.game.xml.SettingsReader;
import fi.honkalampisaatio.game.xml.Setup;
import fi.honkalampisaatio.game.xml.UserSetting;

public class SelectionFrame extends JFrame implements SelectionListener, GameEventListener{

	private static final long serialVersionUID = -386888388601493738L;

	private static final String FILEPATH = "./settings/setup.xml";
	public static final String USERSFOLDER = "./pelaajat/";

	public enum STATES {USER_MENU, USERCOUNT_MENU, GAME_MENU, GAME_RUNNING};
	private STATES state = STATES.USERCOUNT_MENU;

	private GamePanel gp;
	private GameSelection gsp;
	private UserSelection usp;
	private UserCountSelection ucsp;
	private LoadPanel lp;
	
	final static String GAMEPANEL = "Game Panel";
	final static String GAMESELECTIONPANEL = "Game Selection Panel";
	final static String USERSELECTIONPANEL = "User Selection Panel";
	final static String USERCOUNTSELECTIONPANEL = "User Count Selection Panel";
	final static String LOADPANEL = "Load panel";
	
	private JPanel cards;
	
	private ArrayList<UserSetting> userList;
	private Setup setupData;
	
	public SelectionFrame(GamePanel gamePanel) {
		gp = gamePanel;
		try {
			setupData = (Setup) SettingsReader.getInstance().readSettings(
					FILEPATH, Setup.class);
		} catch (JAXBException e) {
			e.printStackTrace();
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(0);
		}
		gp.init(setupData);
		gp.setLanguage(setupData.getLanguageFile());
		
		this.setUndecorated(true);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		Container cPane = this.getContentPane();
		cPane.setLayout(new BorderLayout());
		
		cards = new JPanel(new CardLayout());
		cPane.add(cards);

		lp = new LoadPanel();
		cards.add(lp, LOADPANEL);
		lp.addSelectionListener(this);	
		lp.setVisible(true);	

		this.setVisible(true);
		this.setLocation(0, 0);
		this.setSize(Toolkit.getDefaultToolkit().getScreenSize());	
	}
	
	public void init() {
		

		boolean showUserCountSelection = (setupData.getUsercountList()!=null && setupData.getUsercountList().size()>1);
		usp = new UserSelection(showUserCountSelection, setupData.getShowExitButton());
		cards.add(usp, USERSELECTIONPANEL);
		usp.addSelectionListener(this);	

		ucsp = new UserCountSelection(setupData.getShowExitButton());
		ucsp.setData(setupData.getUsercountList());
		cards.add(ucsp, USERCOUNTSELECTIONPANEL);
		ucsp.addSelectionListener(this);	
		ucsp.setVisible(false);	
		
		gsp = new GameSelection();
		cards.add(gsp, GAMESELECTIONPANEL);
		gsp.addSelectionListener(this);	
		gsp.setVisible(false);	
		
		cards.add(gp, GAMEPANEL);
		gp.setVisible(false);
		gp.setGameEventListener(this);
		
		


		this.addKeyListener(gp);
		this.addKeyListener(gsp);
		
		if(setupData!=null && setupData.getFontData()!=null && 
				setupData.getFontData().getColor()!=null) {
			try {
				Color color = Color.decode(setupData.getFontData().getColor());
				this.setForeground(color);
				gp.setForeground(color);
				usp.setForeground(color);
				ucsp.setForeground(color);
				gsp.setForeground(color);
				lp.setForeground(color);
				System.out.println("Color is " + color.toString());
			}
			catch(NumberFormatException e) {
				e.printStackTrace();
			}
			Font font = Font.decode(setupData.getFontData().getName()+" "+
					setupData.getFontData().getStyle()+" 40");
			if(font!=null) {
				this.setFont(font);
				//showCp, showTimeMeter, showPlayersPanel, showQuestionPanel
				gp.setFont(font);
				usp.setFont(font);
				ucsp.setFont(font);
				gsp.setFont(font);
				lp.setFont(font);
				System.out.println("Font is " + font.toString());
			}
			else
			{
				System.out.println("Creating font " + setupData.getFontData().getName()+" "+
						setupData.getFontData().getStyle() + " failed");
			}
		}
		
		loadContent();
		
		CardLayout cl = (CardLayout)this.cards.getLayout();
		if(showUserCountSelection)
		{
			cl.show(cards, USERCOUNTSELECTIONPANEL);
		}
		else
		{
			state=STATES.USER_MENU;
			usp.setUserCount(1);
			cl.show(cards, USERSELECTIONPANEL);
		}
	}
	
	protected void loadContent()
	{
		MediaResource mr = MediaResource.getInstance();
		File folder = new File(SelectionFrame.USERSFOLDER);
		    
		if (folder.exists()) {
		    File[] listOfFiles = folder.listFiles();
		    for (int i = 0; i < listOfFiles.length; i++) {
			      if (listOfFiles[i].isFile()) {
			    	  String filename = listOfFiles[i].getName();
			    	  String ext = filename.substring(filename.lastIndexOf('.')+1,filename.length());
			    	if (ext.equalsIgnoreCase("xml") ) {  
				        File file = listOfFiles[i];
						UserSetting user = null; 
						try {
							user = (UserSetting) SettingsReader.getInstance().readSettings(
									file.getPath(), UserSetting.class);
						} catch (JAXBException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
						if(!mr.containsKey(user.getMenuImage()))
							mr.setImage(user.getMenuImage());
						ArrayList<String> gamePaths = user.getGameFileList();
						for(int gi=0; gi<gamePaths.size(); gi++)
						{
							loadGameContent(gamePaths.get(gi));
						}
			      	}
			      }
			    }
		}
	}
	
	protected void loadGameContent(String gameFilePath)
	{
		MediaResource mr = MediaResource.getInstance();
		GameSettings gameSetting = null;
		try {
			gameSetting = (GameSettings) SettingsReader.getInstance().readSettings(
					gameFilePath, gp.getSettingsClass());
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(gameSetting!=null)
		{
			if(!mr.containsKey(gameSetting.getMenuImage()))
				mr.setImage(gameSetting.getMenuImage());
		}
	}

	protected void selectGame(GameSettings sets) {
		
		GameLogger.getInstance().setFiles(userList, sets.getLogFileName());
		
		gp.requestFocus();
		gp.setGameSettings(sets.getSetupFile());

		gp.startGame();
	}
	
	protected void startExternalProgram(String fileName, String workDir) {
        try {
            System.out.println(fileName+" käyntiin");
            File directory = new File(workDir);
            String[] envp = {};
			Process p = Runtime.getRuntime().exec(
					fileName, envp, directory);
			
			BufferedReader br = new BufferedReader(new
							InputStreamReader(p.getInputStream()));
			@SuppressWarnings("unused")
			String line;
			while((line = br.readLine()) != null) {
				;
			}
            System.out.println(fileName+" sammutettu");
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		state=STATES.GAME_MENU;
		System.out.println("Tila: " + state.toString());
	}


	protected void selectUser(ArrayList<UserSetting> userList) {
		gsp.setUsers(userList, gp.getSettingsClass());
		gp.setUsers(userList);
		//gsp.requestFocus();
	}
	
	@Override
	public void selectionEventOccurred(EventObject event) {
		final EventObject se = event;
		final CardLayout cl = (CardLayout)this.cards.getLayout();
		cl.show(cards, LOADPANEL);
		
		SwingUtilities.invokeLater(new Runnable() {
            public void run() {
        		if(se instanceof UserSelectionEvent && state==STATES.USER_MENU) {
        			UserSelectionEvent event = (UserSelectionEvent)se;
        			if(event.getUserList()==null || event.getUserList().isEmpty()) {
        				state=STATES.USERCOUNT_MENU;
        				usp.setUserCount(0);
        				System.out.println("Tila: " + state.toString());
        				cl.show(cards, USERCOUNTSELECTIONPANEL);	
        			}
        			else {
        				state=STATES.GAME_MENU;
        				System.out.println("Tila: " + state.toString());
        				userList = event.getUserList();
        				selectUser(userList);
        				cl.show(cards, GAMESELECTIONPANEL);	
        			}
        		}
        		else if(se instanceof UserCountSelectionEvent && state==STATES.USERCOUNT_MENU) {
        			state=STATES.USER_MENU;
        			System.out.println("Tila: " + state.toString());
        			usp.setUserCount(((UserCountSelectionEvent)se).getUserCount());
        			cl.show(cards, USERSELECTIONPANEL);	
        		}
        		else if(se instanceof GameSelectionEvent && state==STATES.GAME_MENU) {
        			GameSelectionEvent event = (GameSelectionEvent)se;
        			if(event.getGame()==null) {
        				state=STATES.USER_MENU;
        				usp.clearSelections();
        				gp.setUsers(null);
        				System.out.println("Tila: " + state.toString());
        				cl.show(cards, USERSELECTIONPANEL);		
        			}
        			else {
        				state=STATES.GAME_RUNNING;
        				System.out.println("Tila: " + state.toString());
        		    	String ext = event.getGame().getSetupFile().substring(
        		    			event.getGame().getSetupFile().lastIndexOf('.')+1,
        		    			event.getGame().getSetupFile().length());
        				if(ext.equalsIgnoreCase("xml"))
        				{
        					selectGame(event.getGame());
        					cl.show(cards, GAMEPANEL);
        				}
        				/*
        				else
        				{
        					final String fileName = event.getGame().getSetupFile();
        					final String workDir = event.getGame().getWorkDirectory();
        					Thread t = new Thread(new Runnable() {

        						@Override
        						public void run() {
        							startExternalProgram(fileName, workDir);
        						}});
        					t.start();
        				}
        				*/
        			}
        		}
              }
            });
	}

	@Override
	public void gameEventOccurred(GameEvent e) {
		if (e.type == GameEvent.TYPE.GAME_END && state==STATES.GAME_RUNNING) {
			CardLayout cl = (CardLayout)this.cards.getLayout();
			cl.show(cards, GAMESELECTIONPANEL);		
			//gsp.requestFocus();
			state=STATES.GAME_MENU;
			System.out.println("Tila: " + state.toString());
		}
	}
}
